﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using Bridge.Base.Constructs;
using Bridge.Base.Converter;
using Bridge.Base.Utilities;
using Bridge.Objects;
using Microsoft.Win32;

namespace Bridge.UI
{
    /// <summary>
    /// Interaction logic for ExportCharacter.xaml
    /// </summary>
    public partial class ExportCharacter : UserControl
    {
        /// <summary>
        /// Default constructor for export character.
        /// </summary>
        public ExportCharacter()
        {
            InitializeComponent();

            mEventHandler = new EventHandler(UpdateAllEngines);
            Main.AssembliesReloaded += mEventHandler;
        }

        /// <summary>
        /// Deconstructor for ExportCharacter.
        /// </summary>
        ~ExportCharacter()
        {
            Main.AssembliesReloaded -= mEventHandler;
        }

        /// <summary>
        /// Called when a character is selected.
        /// </summary>
        /// <param name="character">Character selected.</param>
        public void CharacterSelected(Character character)
        {
            if (character == null) return;

            mCharacter = character;
            string lastSelection = null;
            Dictionary<string, object> values = new Dictionary<string, object>();
            if (comboBoxExportCharacterEngine.SelectedItem != null)
            {
                lastSelection = comboBoxExportCharacterEngine.SelectedItem.ToString();

                foreach (ConverterPropertyView converterPropertyView in listBoxProperties.Items)
                {
                    values.Add(converterPropertyView.Key, converterPropertyView.Value);
                }
            }

            comboBoxExportCharacterEngine.Items.Clear();
            string newSelection = null;
            foreach (KeyValuePair<CharacterOutputConverter, string> engine in mEngines)
            {
                if (engine.Value.Equals(character.CharacterType, StringComparison.OrdinalIgnoreCase))
                {
                    string converterName = engine.Key.GetConverterName();
                    comboBoxExportCharacterEngine.Items.Add(converterName);
                    if (!string.IsNullOrEmpty(lastSelection) && converterName.Equals(lastSelection, StringComparison.OrdinalIgnoreCase))
                    {
                        newSelection = converterName;
                    }
                }
            }

            if (!string.IsNullOrEmpty(newSelection))
            {
                comboBoxExportCharacterEngine.SelectedItem = newSelection;
                foreach (ConverterPropertyView converterPropertyView in listBoxProperties.Items)
                {
                    if (values.ContainsKey(converterPropertyView.Key))
                    {
                        converterPropertyView.Value = values[converterPropertyView.Key];
                    }
                }
            }
        }

        private Dictionary<CharacterOutputConverter, string> mEngines = new Dictionary<CharacterOutputConverter, string>();
        private Character mCharacter;
        private EventHandler mEventHandler;

        private void UpdateAllEngines(object sender, EventArgs e)
        {
            mEngines.Clear();
            foreach (Type type in typeof(CharacterOutputConverter).GetCompatibleTypes())
            {
                CharacterOutputConverter characterOutputConverter = (CharacterOutputConverter)type.GetConstructor(Type.EmptyTypes).Invoke(null);
                Character defaultCharacter = (Character)characterOutputConverter.GetCharacterType().GetConstructor(Type.EmptyTypes).Invoke(null);
                string defaultCharacterType = defaultCharacter.CharacterType;
                if (!mEngines.ContainsKey(characterOutputConverter))
                {
                    mEngines.Add(characterOutputConverter, defaultCharacterType);
                }
            }
        }

        private void buttonListBoxPropertiesBrowse_Click(object sender, RoutedEventArgs e)
        {
            Button buttonSender = (Button)sender;
            string key = (string)buttonSender.Tag;

            foreach (ConverterPropertyView converterPropertyView in listBoxProperties.Items)
            {
                if (converterPropertyView.Key.Equals(key, StringComparison.OrdinalIgnoreCase))
                {
                    OpenFileDialog openFileDialog = new OpenFileDialog()
                    {
                        CheckFileExists = true,
                        CheckPathExists = true,
                        Multiselect = false,
                        Filter = converterPropertyView.ConverterProperty.FilterExtensions
                    };
                    if (openFileDialog.ShowDialog() == true)
                    {
                        converterPropertyView.Value = openFileDialog.FileName;
                    }
                    return;
                }
            }
        }

        private void buttonOutputLocation_Click(object sender, RoutedEventArgs e)
        {
            if (comboBoxExportCharacterEngine.SelectedItem == null) return;

            string selectedItem = (string)comboBoxExportCharacterEngine.SelectedItem;
            CharacterOutputConverter converter = null;
            foreach (KeyValuePair<CharacterOutputConverter, string> engine in mEngines)
            {
                if (engine.Key.GetConverterName().Equals(selectedItem, StringComparison.OrdinalIgnoreCase))
                {
                    converter = engine.Key;
                    break;
                }
            }
            if (converter != null)
            {

                SaveFileDialog saveFileDialog = new SaveFileDialog()
                {
                    CheckPathExists = true,
                    OverwritePrompt = true,
                    Title = "Save Character Location",
                    DefaultExt = converter.GetDefaultExtension(),
                    Filter = converter.GetOutputExtensions(),
                    FileName = textBoxOutputLocation.Text
                };
                if (saveFileDialog.ShowDialog() == true)
                {
                    textBoxOutputLocation.Text = saveFileDialog.FileName;
                }
            }

        }

        private void comboBoxExportCharacterEngine_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (comboBoxExportCharacterEngine.SelectedItem == null) return;

            string selectedItem = (string)comboBoxExportCharacterEngine.SelectedItem;
            CharacterOutputConverter converter = null;
            foreach (KeyValuePair<CharacterOutputConverter, string> engine in mEngines)
            {
                if (engine.Key.GetConverterName().Equals(selectedItem, StringComparison.OrdinalIgnoreCase))
                {
                    converter = engine.Key;
                    break;
                }
            }
            if (converter != null)
            {
                listBoxProperties.Items.Clear();
                foreach (ConverterProperty converterProperty in converter.GetConverterProperties())
                {
                    listBoxProperties.Items.Add(new ConverterPropertyView(converterProperty));
                }
            }
        }

        private void buttonExport_Click(object sender, RoutedEventArgs e)
        {
            if (comboBoxExportCharacterEngine.SelectedItem == null)
            {
                textBlockInvalid.Text = "No engine is selected.";
            }
            if (mCharacter == null)
            {
                return;
            }
            List<ConverterProperty> properties = new List<ConverterProperty>();
            foreach (ConverterPropertyView converterPropertyView in listBoxProperties.Items)
            {
                if (!converterPropertyView.IsValid)
                {
                    textBlockInvalid.Text = string.Format("Property {0} is not valid.", converterPropertyView.Key);
                    return;
                }
                properties.Add(converterPropertyView.ConverterProperty);
            }

            string selectedItem = (string)comboBoxExportCharacterEngine.SelectedItem;
            CharacterOutputConverter converter = null;
            foreach (KeyValuePair<CharacterOutputConverter, string> engine in mEngines)
            {
                if (engine.Key.GetConverterName().Equals(selectedItem, StringComparison.OrdinalIgnoreCase))
                {
                    converter = engine.Key;
                    break;
                }
            }
            if (converter != null)
            {
                DateTime startTime = DateTime.Now;
                try
                {
                    if (converter.OutputCharacter(mCharacter, new System.IO.FileInfo(textBoxOutputLocation.Text), properties))
                    {
                        TimeSpan endTime = DateTime.Now.Subtract(startTime);
                        WarningWindow.ShowWarning(WarningWindow.WarningType.OK, "Character exported successfully.");
                        Log.MetricsLog.InfoFormat("Exported {0} using {1}, Time Taken: {2}", mCharacter.Name, converter.GetConverterName(), endTime);
                    }
                    else
                    {
                        WarningWindow.ShowWarning(WarningWindow.WarningType.OK, "Could not create output character");
                    }
                }
                catch (Exception ex)
                {
                    Log.NormalLog.Warn(string.Format("Attempting to export {0} using {1} failed.", mCharacter.Name, converter.GetConverterName()), ex);
                    WarningWindow.ShowWarning(WarningWindow.WarningType.OK, string.Format("Unable to export character due to severe error. This is a export package error. Let the package author know of this error.\nException Time: {0}", DateTime.Now), ex.ToString(), "Export Character Exception");
                }
            }
        }
    }
}
